<template>
  <vol-box :lazy="false" :model.sync="model" title="配置" :height="500" :width="800"
    :padding="0">
    <div style="display: flex;height: 100%">
      <div style="width: 300px;border-right: 1px solid #dce3e8;">
        <node-menu @addNode="addNode" ref="nodeMenu" @imgURL="imgURL"></node-menu>
      </div>
      <div id="efContainer" ref="efContainer" class="container" v-flowDrag
        :style="{backgroundImage:'url('+SRCL+backgroundpic+')'}">
        <template v-for="node in data.nodeList">
          <flow-node :id="node.id" :key="node.id" :node="node" :activeElement="activeElement"
            @deleteNode="deleteNode" @changeNodeSite="changeNodeSite" @nodeRightMenu="nodeRightMenu"
            @clickNode="clickNode">
          </flow-node>
        </template>
      </div>
    </div>
    <div slot="footer">
      <Button type="primary" @click="saveAll()">保存</Button>
      <Button type="default" @click="() => (this.model = false)">关闭</Button>
    </div>
  </vol-box>
</template>

<script>
import VolBox from "@/components/basic/VolBox.vue";
import draggable from "vuedraggable";
// import "@/assets/script/jsplumb.js";
import { easyFlowMixin } from "@/assets/script/mixins.js";
import flowNode from "./node";
import nodeMenu from "./node_menu";
import lodash from "lodash";

export default {
  data() {
    return {
      worktableNameList: [],
      isAdd: false,
      model: false,
      height: 800,
      row: null,
      // jsPlumb 实例
      jsPlumb: null,
      // 控制画布销毁
      // 控制流程数据显示与隐藏
      flowInfoVisible: false,
      // 是否加载完毕标志位
      loadEasyFlowFinish: false,
      flowHelpVisible: false,
      // 数据
      data: {},
      // 激活的元素、可能是节点、可能是连线
      activeElement: {
        // 可选值 node 、line
        type: undefined,
        // 节点ID
        nodeId: undefined,
        // 连线ID
        sourceId: undefined,
        targetId: undefined,
      },
      zoom: 0.5,
      backgroundpic: "",
      SRCL: "",
      configurat: {},
    };
  },
  // 一些基础配置移动该文件中
  mixins: [easyFlowMixin],
  components: {
    draggable,
    VolBox,
    nodeMenu,
    flowNode,
  },
  directives: {
    flowDrag: {
      bind(el, binding, vnode, oldNode) {
        if (!binding) {
          return;
        }
        el.onmousedown = (e) => {
          if (e.button == 2) {
            // 右键不管
            return;
          }
          //  鼠标按下，计算当前原始距离可视区的高度
          let disX = e.clientX;
          let disY = e.clientY;
          el.style.cursor = "move";

          document.onmousemove = function (e) {
            // 移动时禁止默认事件
            e.preventDefault();
            const left = e.clientX - disX;
            disX = e.clientX;
            el.scrollLeft += -left;

            const top = e.clientY - disY;
            disY = e.clientY;
            el.scrollTop += -top;
          };

          document.onmouseup = function (e) {
            el.style.cursor = "auto";
            document.onmousemove = null;
            document.onmouseup = null;
          };
        };
      },
    },
  },
  mounted() {
    this.SRCL = this.http.ipAddress;
    this.jsPlumb = jsPlumb.getInstance();
  },
  methods: {
    open() {
      this.model = true;
      this.data.nodeList = [];
      let parmas = {
        order: "desc",
        page: 1,
        rows: 30,
        sort: "id",
        wheres: "[]",
      };
      this.http
        .post("/api/Mall_camp_configuration/getPageData", parmas)
        .then((res) => {
          if (res.rows.length != 0) {
            this.isAdd = false;
            let row = res.rows[0];
            this.configurat = row;
            this.$nextTick(() => {
              let configurationjson = JSON.parse(row.configurationjson);
              this.data.nodeList = configurationjson.map((i) => {
                return {
                  id: i.id,
                  name: i.name,
                  left: i.positionx,
                  top: i.positiony,
                  type: i.fieldkey,
                };
              });
              this.backgroundpic = row.configurationurl;
              this.data = lodash.cloneDeep(this.data);
              this.$nextTick(() => {
                this.jsPlumb = jsPlumb.getInstance();
                this.$nextTick(() => {
                  this.jsPlumbInit();
                });
              });
            });
            this.$refs.nodeMenu.setPIC(this.backgroundpic);
          } else {
            this.data.nodeList = [];
            this.isAdd = true;
          }
        });
    },
    imgURL(e) {
      this.backgroundpic = e;
    },

    // 返回唯一标识
    getUUID() {
      return Math.random().toString(36).substr(3, 10);
    },
    jsPlumbInit() {
      this.jsPlumb.ready(() => {
        // 导入默认配置
        this.jsPlumb.importDefaults(this.jsplumbSetting);
        // 会使整个jsPlumb立即重绘。
        this.jsPlumb.setSuspendDrawing(false, true);
        // 初始化节点
        this.loadEasyFlow();
      });
    },
    // 加载流程图
    loadEasyFlow() {
      // 初始化节点
      for (var i = 0; i < this.data.nodeList.length; i++) {
        let node = this.data.nodeList[i];
        // 设置源点，可以拖出线连接其他节点
        this.jsPlumb.makeSource(
          node.id,
          lodash.merge(this.jsplumbSourceOptions, {})
        );
        // // 设置目标点，其他源点拖出的线可以连接该节点
        this.jsPlumb.makeTarget(node.id, this.jsplumbTargetOptions);
        if (!node.viewOnly) {
          this.jsPlumb.draggable(node.id, {
            containment: "parent",
            stop: function (el) {
              // 拖拽节点结束后的对调
              console.log("拖拽结束: ", el);
            },
          });
        }
      }
      this.$nextTick(function () {
        this.loadEasyFlowFinish = true;
      });
    },
    // 设置连线条件
    setLineLabel(from, to, label) {
      var conn = this.jsPlumb.getConnections({
        source: from,
        target: to,
      })[0];
      if (!label || label === "") {
        conn.removeClass("flowLabel");
        conn.addClass("emptyFlowLabel");
      } else {
        conn.addClass("flowLabel");
      }
      conn.setLabel({
        label: label,
      });
    },
    // 改变节点的位置
    changeNodeSite(data) {
      for (var i = 0; i < this.data.nodeList.length; i++) {
        let node = this.data.nodeList[i];
        if (node.id === data.nodeId) {
          node.left = data.left;
          node.top = data.top;
        }
      }
    },
    /**
     * 拖拽结束后添加新的节点
     * @param evt
     * @param nodeMenu 被添加的节点对象
     * @param mousePosition 鼠标拖拽结束的坐标
     */
    addNode(evt, nodeMenu, mousePosition) {
      var screenX = evt.originalEvent.clientX,
        screenY = evt.originalEvent.clientY;
      let efContainer = this.$refs.efContainer;
      var containerRect = efContainer.getBoundingClientRect();
      var left = screenX,
        top = screenY;
      // 计算是否拖入到容器中
      if (
        left < containerRect.x ||
        left > containerRect.width + containerRect.x ||
        top < containerRect.y ||
        containerRect.y > containerRect.y + containerRect.height
      ) {
        this.$message.error("请把节点拖入到画布中");
        return;
      }
      left = left - containerRect.x + efContainer.scrollLeft;
      top = top - containerRect.y + efContainer.scrollTop;
      // 居中
      left -= 85;
      top -= 16;
      var nodeId = this.getUUID();
      // 动态生成名字
      var origName = nodeMenu.name;
      var nodeName = origName;
      var index = 1;
      while (index < 10000) {
        var repeat = false;
        for (var i = 0; i < this.data.nodeList.length; i++) {
          let node = this.data.nodeList[i];
          if (node.name === nodeName) {
            nodeName = origName + index;
            repeat = true;
          }
        }
        if (repeat) {
          index++;
          continue;
        }
        break;
      }
      var node = {
        id: nodeId,
        name: nodeName,
        type: nodeMenu.type,
        left: left + "px",
        top: top + "px"
      };
      /**
       * 这里可以进行业务判断、是否能够添加该节点
       */
      this.data.nodeList.push(node);
      this.$nextTick(function () {
        this.jsPlumb.makeSource(nodeId, this.jsplumbSourceOptions);
        this.jsPlumb.makeTarget(nodeId, this.jsplumbTargetOptions);
        this.jsPlumb.draggable(nodeId, {
          containment: "parent",
          stop: function (el) {
            // 拖拽节点结束后的对调
            console.log("拖拽结束: ", el);
          },
        });
      });
    },
    /**
     * 删除节点
     * @param nodeId 被删除节点的ID
     */
    deleteNode(nodeId) {
      this.data.nodeList = this.data.nodeList.filter(function (node) {
        if (node.id === nodeId) {
          return false;
        }
        return true;
      });
      this.$nextTick(function () {
        this.jsPlumb.removeAllEndpoints(nodeId);
      });
      return true;
    },
    clickNode(nodeId) {
      this.activeElement.type = "node";
      this.activeElement.nodeId = nodeId;
    },
    nodeRightMenu(nodeId, evt) {
      this.menu.show = true;
      this.menu.curNodeId = nodeId;
      this.menu.left = evt.x + "px";
      this.menu.top = evt.y + "px";
    },
    // 保存全部数据
    saveAll() {
      let arr = this.data.nodeList.map((i) => {
        return {
          id: i.id,
          name: i.name,
          positionx: i.left,
          positiony: i.top,
          fieldkey: i.type,
          fieldvalue: "",
        };
      });
      let params = {
        delKeys: null,
        detailData: null,
        mainData: {
          configurationtype: 0,
          configurationurl: this.backgroundpic,
          configurationjson: arr,
        },
      };

      if (this.isAdd) {
        this.http
          .post("/api/Mall_camp_configuration/Add", params)
          .then((res) => {
            if (res.status) {
              this.model = false;
              this.$Message.success(res.message);
            } else {
              this.model = true;
              this.$Message.error(res.message);
            }
          });
      } else {
        params.mainData.id = this.configurat.id;
        this.http
          .post("/api/Mall_camp_configuration/Update", params)
          .then((res) => {
            if (res.status) {
              this.model = false;
              this.$Message.success(res.message);
            } else {
              this.model = true;
              this.$Message.error(res.message);
            }
          });
      }
    },
  },
};
</script>
<style lang="less" scoped>
/*画布容器*/
#efContainer {
  position: relative;
  overflow: scroll;
  flex: 1;
  background-size: 100% 100%;
  width: 500px;
  height: 500px;
}

/*顶部工具栏*/
.ef-tooltar {
  padding-top: 10px;
  padding-left: 10px;
  box-sizing: border-box;
  height: 52px;
  line-height: 52px;
  z-index: 3;
  border-bottom: 1px solid #dadce0;
}

.jtk-overlay {
  cursor: pointer;
  color: #4a4a4a;
}

/*节点菜单*/
.ef-node-pmenu {
  cursor: pointer;
  height: 32px;
  line-height: 32px;
  width: 225px;
  display: block;
  font-weight: bold;
  color: #4a4a4a;
  padding-left: 5px;
}

.ef-node-pmenu:hover {
  background-color: #e0e0e0;
}

.ef-node-menu-li {
  color: #565758;
  width: 150px;
  border: 1px dashed #e0e3e7;
  margin: 5px 0 5px 0;
  padding: 5px;
  border-radius: 5px;
  padding-left: 8px;
}

.ef-node-menu-li:hover {
  /* 设置移动样式*/
  cursor: move;
  background-color: #f0f7ff;
  border: 1px dashed #1879ff;
  border-left: 4px solid #1879ff;
  padding-left: 5px;
}

.ef-node-menu-ul {
  list-style: none;
  padding-left: 20px;
  /* border: 1px dashed #1879FF; */
}

/*节点的最外层容器*/
.ef-node-container {
  position: absolute;
  display: flex;
  width: 100px;
  height: 32px;
  border: 1px solid #e0e3e7;
  border-radius: 5px;
  background-color: #fff;
}

.ef-node-container:hover {
  /* 设置移动样式*/
  cursor: move;
  background-color: #f0f7ff;
  /*box-shadow: #1879FF 0px 0px 12px 0px;*/
  background-color: #f0f7ff;
  border: 1px dashed #1879ff;
}

/*节点激活样式*/
.ef-node-active {
  background-color: #f0f7ff;
  /*box-shadow: #1879FF 0px 0px 12px 0px;*/
  background-color: #f0f7ff;
  border: 1px solid #1879ff;
}

/*节点左侧的竖线*/
.ef-node-left {
  width: 4px;
  background-color: #1879ff;
  border-radius: 4px 0 0 4px;
}

/*节点左侧的图标*/
.ef-node-left-ico {
  line-height: 32px;
  margin-left: 8px;
}

.ef-node-left-ico:hover {
  /* 设置拖拽的样式 */
  cursor: crosshair;
}

/*节点显示的文字*/
.ef-node-text {
  color: #565758;
  font-size: 12px;
  line-height: 32px;
  margin-left: 8px;
  width: 100px;
  /* 设置超出宽度文本显示方式*/
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
}

/*节点右侧的图标*/
.ef-node-right-ico {
  line-height: 32px;
  position: absolute;
  right: 5px;
  color: #84cf65;
  cursor: default;
}

/*节点的几种状态样式*/
.el-node-state-success {
  line-height: 32px;
  position: absolute;
  right: 5px;
  color: #84cf65;
  cursor: default;
}

.el-node-state-error {
  line-height: 32px;
  position: absolute;
  right: 5px;
  color: #f56c6c;
  cursor: default;
}

.el-node-state-warning {
  line-height: 32px;
  position: absolute;
  right: 5px;
  color: #e6a23c;
  cursor: default;
}

.el-node-state-running {
  line-height: 32px;
  position: absolute;
  right: 5px;
  color: #84cf65;
  cursor: default;
}

/*node-form*/
.ef-node-form-header {
  height: 32px;
  border-top: 1px solid #dce3e8;
  border-bottom: 1px solid #dce3e8;
  background: #f1f3f4;
  color: #000;
  line-height: 32px;
  padding-left: 12px;
  font-size: 14px;
}

.ef-node-form-body {
  margin-top: 10px;
  padding-right: 10px;
  padding-bottom: 20px;
}

/* 连线中的label 样式*/
.jtk-overlay.flowLabel:not(.aLabel) {
  padding: 4px 10px;
  background-color: white;
  color: #565758 !important;
  border: 1px solid #e0e3e7;
  border-radius: 5px;
}

/* label 为空的样式 */
.emptyFlowLabel {
}

.ef-dot {
  background-color: #1879ff;
  border-radius: 10px;
}

.ef-dot-hover {
  background-color: red;
}

.ef-rectangle {
  background-color: #1879ff;
}

.ef-rectangle-hover {
  background-color: red;
}

.ef-img {
}

.ef-img-hover {
}

.ef-drop-hover {
  border: 1px dashed #1879ff;
}
</style>